package com.pantech.app.call_log_enabler;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;

public class ProcessService extends Service {
	
	private static final String LOG_TAG = "LogApp";
	
	private UserSharedPreference mUserSharedPreference;
	
	static final String Log_path = "/calllog_app/";
    static final String Log_path_VT = "/calllog/";
    static final String Folder_path = Environment.getExternalStorageDirectory().getPath();
    
    public static String fileName = null;
    public static String arg_ddms = null;
    public static String arg_pcap = null;
    public static String arg_radio = null;
    
    public final String pref_CALLLOG_ONGOING = UserSharedPreference.pref_CALLLOG_ONGOING;
    public final String pref_UDP_CHECKED = UserSharedPreference.pref_UDP_CHECKED;
    public final String pref_DDMS_CHECKED = UserSharedPreference.pref_DDMS_CHECKED;
    public final String pref_PCAP_CHECKED = UserSharedPreference.pref_PCAP_CHECKED;
    public final String pref_RADIO_CHECKED = UserSharedPreference.pref_RADIO_CHECKED;
    public final String pref_REMOVE_BUFFER_CHECKED = UserSharedPreference.pref_REMOVE_BUFFER_CHECKED;
    public final String pref_IS_BUSYBOX_EXIST = UserSharedPreference.pref_IS_BUSYBOX_EXIST;
    public final int DDMS = 1;
    public final int PCAP = 2;
    public final int RADIO = 3;
    static final int PROCESS_NOW = 0;
    static final int PROCESS_BEFORE = 1;
    static boolean isBusyboxExist = false;
    
    static int numbers = 0;
    
    Process ddms_process = null;
    Process pcap_process = null;
	Process radio_process = null;
	Timer mTimer;

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		
		//unregister alarm
		Intent intent = new Intent(ProcessService.this, SwitchReceiver.class);
		intent.setAction(SwitchReceiver.ACTION_RESTART_PROCESSSERVICE);
		PendingIntent sender = PendingIntent.getBroadcast(ProcessService.this, 0, intent, 0);
		AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
	    am.cancel(sender);
	    
		mUserSharedPreference = new UserSharedPreference(getApplicationContext());
		isBusyboxExist = getBoolean_pref(pref_IS_BUSYBOX_EXIST);
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		
		setBoolean_pref(pref_CALLLOG_ONGOING, false); //should be before destroyLogProcess()
		destroyLogProcess();
		
    	//update Media DB for MTP
    	sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
                + (new File(String.format("" + Folder_path + Log_path))))));
    	
    	if(MainActivity.isLogEnabled_applog) {
			//register alram
			Intent intent = new Intent(ProcessService.this, SwitchReceiver.class);
			intent.setAction(SwitchReceiver.ACTION_RESTART_PROCESSSERVICE);
			PendingIntent sender = PendingIntent.getBroadcast(ProcessService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
			long firstTime = SystemClock.elapsedRealtime();
			firstTime += 0.1*1000;
			AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
			am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 5*1000, sender);
		}
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		
		runLogProcess();
    	
		return super.onStartCommand(intent, flags, startId);
	}
	
	public void runLogProcess() {
		Log.d(LOG_TAG, "Make log Start");
		numbers = 0;
    	
    	File file = new File(String.format("" + Folder_path + Log_path));
    	if(file.mkdirs() || file.isDirectory()) {
    	} else {
    		ShowToast("Make directory failed!!", Toast.LENGTH_SHORT);
    		stopSelf();
    		return;
    	}
    	
    	fileName = String.format("" + Folder_path + Log_path + "callLog_" + getTime(true));
    	arg_ddms = String.format(fileName + ".txt");
    	arg_pcap = String.format(fileName + ".pcap");
    	arg_radio = String.format(fileName + "_radio.txt");
    	
    	//run Build process
    	new Thread(new Runnable() {
            @Override
            public void run() {
            	setBoolean_pref(pref_CALLLOG_ONGOING, true); //this should be before LogProcess(s)
            	if(getBoolean_pref(pref_REMOVE_BUFFER_CHECKED)) {
        			clearBuffer();
        		}
            	ddmsLogProcess();
            	pcapLogProcess();
            }
        }).start();
    	
    	TimerTask logTask = new TimerTask() {
    		public void run() {
    			Log.d(LOG_TAG, "Make log > continue ddms log");
    			numbers++;
    			clearBuffer();
    			ddmsDestroyLogProcess(String.format(fileName + "_" + numbers), false);
    			ddmsLogProcess();
    		}
    	};
    	mTimer = new Timer();
    	mTimer.schedule(logTask, 60 * 60 * 1000, 60 * 60 * 1000);
    	
    	//run Build process - end
	}
	
	public void ddmsLogProcess() {
		String[] commands_ddms = {"logcat", "-v", "time", "-f", arg_ddms.toString()};
    	ProcessBuilder pb_ddms = new ProcessBuilder(commands_ddms);
    	pb_ddms.redirectErrorStream(true);
    	
    	String[] commands_radio = {"logcat", "-v", "time", "-b", "radio", "-f", arg_radio.toString()};
    	ProcessBuilder pb_radio = new ProcessBuilder(commands_radio);
    	pb_radio.redirectErrorStream(true);
    	
    	try {
			if(getBoolean_pref(pref_DDMS_CHECKED)) {
				ddms_process = pb_ddms.start();
        		Log.d(LOG_TAG, "Make log path logcat : " + arg_ddms);
    		} else {
    			pb_ddms = null;
    		}
    		
    		if(getBoolean_pref(pref_RADIO_CHECKED)) {
    			radio_process = pb_radio.start();
        		Log.d(LOG_TAG, "Make log path radio : " + arg_radio);
    		} else {
    			pb_radio = null;
    		}
		} catch (IOException e) {
			Log.d(LOG_TAG, "make log > ddmsLogProcess()) error");
			destroyLogProcess();
			setBoolean_pref(pref_CALLLOG_ONGOING, false);
			e.printStackTrace();
		}
	}
	
	public void pcapLogProcess() {
		ProcessBuilder pb_pcap;
    	if(getBoolean_pref(pref_UDP_CHECKED)) {
    		String[] commands_pcap = {"tcpdump", "-i", "any", "-p", "-s", "0", "-w", arg_pcap.toString(), "-U", "udp"};
    		pb_pcap = new ProcessBuilder(commands_pcap);
    	} else {
    		String[] commands_pcap = {"tcpdump", "-i", "any", "-p", "-s", "0", "-w", arg_pcap.toString(), "-U"};
    		pb_pcap = new ProcessBuilder(commands_pcap);
    	}
    	pb_pcap.redirectErrorStream(true);
    	
    	try {	
    		if(getBoolean_pref(pref_PCAP_CHECKED)) {
    			pcap_process = pb_pcap.start();
        		Log.d(LOG_TAG, "Make log path pcap : " + arg_pcap);
    		} else {
    			pb_pcap = null;
    		} 	
		} catch (IOException e) {
			Log.d(LOG_TAG, "make log > pcapLogProcess() error");
			destroyLogProcess();
			setBoolean_pref(pref_CALLLOG_ONGOING, false);
			e.printStackTrace();
		}
	}
	
	public void clearBuffer() {
		Log.d(LOG_TAG, "Make log - Clear buffer");
		if(getBoolean_pref(pref_DDMS_CHECKED)) {
			try {
				new ProcessBuilder("logcat", "-c").start();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(getBoolean_pref(pref_RADIO_CHECKED)) {
			try {
				new ProcessBuilder("logcat", "-c", "-b", "radio").start();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void destroyLogProcess() {
    	Log.e(LOG_TAG,"Make log is onging - kill log process");
    	
    	mTimer.cancel();
    	
    	if(numbers == 0)
    		fileName = String.format(fileName + "_" + getTime(false));
    	else
    		fileName = String.format(fileName + "_" + ++numbers + "_" + getTime(false));
		
    	ddmsDestroyLogProcess(fileName, true);
    	pcapDestroyLogProcess(fileName); 
    }
	
	public void ddmsDestroyLogProcess(String mfileName, boolean isFinish) {
		if(ddms_process != null) {
    		ddms_process.destroy();
    		ddms_process = null;
    	}
		if(radio_process != null) {
			radio_process.destroy();
			radio_process = null;
		}
		
		if(MainActivity.isEngBinary && isBusyboxExist) {
			Process process_ddms = null;
	    	try {
	        	ProcessBuilder exec_ddms = new ProcessBuilder("/system/bin/sh", "-c", "kill $(ps | busybox grep 'logcat' | busybox awk '{print $2}')");
	        	process_ddms = exec_ddms.start();
			} catch (IOException e) {
				if (process_ddms!=null) process_ddms.destroy();
				setBoolean_pref(pref_CALLLOG_ONGOING, true);
				e.printStackTrace();
			}
		}else {
			Log.e(LOG_TAG,"Make log doesn't have busy box");
		}
		
		if(reNameFile(new File(arg_ddms), new File(mfileName + ".txt"))) {
			if(isFinish) {
				arg_ddms = mfileName + ".txt";
			}
	    }
		if(reNameFile(new File(arg_radio), new File(mfileName + "_radio.txt"))) {
			if(isFinish) {
				arg_radio = mfileName + "_radio.txt";
			}
	    }
	}
	
	public void pcapDestroyLogProcess(String mfileName) {
		if(pcap_process != null) {
    		pcap_process.destroy();
    		pcap_process = null;
		}
		
		if(MainActivity.isEngBinary && isBusyboxExist) {
	    	Process process_pcap = null;
			try {
				ProcessBuilder exec_pcap = new ProcessBuilder("/system/bin/sh", "-c", "kill $(ps | busybox grep 'tcpdump' | busybox awk '{print $2}')");
				process_pcap = exec_pcap.start();
			} catch (IOException e) {
				if (process_pcap!=null) process_pcap.destroy();
				setBoolean_pref(pref_CALLLOG_ONGOING, true);
				e.printStackTrace();
			}
		}else {
			Log.e(LOG_TAG,"Make log doesn't have busy box");
		}
		
		if(reNameFile(new File(arg_pcap), new File(mfileName + ".pcap"))) {
	    	arg_pcap = mfileName + ".pcap";
	    }
	}

	public void ShowToast(String string, int time) {
		Toast m_Toast = MainActivity.m_Toast;
		if(m_Toast != null) {     
			m_Toast.setText(string); 
			m_Toast.show();
		}else {
			m_Toast = Toast.makeText(getApplicationContext(), string, time);
			m_Toast.show();
		}
    }
	
	private boolean reNameFile(File file, File new_name) {
    	if(file!=null && file.exists() && file.renameTo(new_name)) {
    		return true;
    	} else {
    		return false;
    	}
    }
	
	public String getTime(boolean dayORtime) {
		final Calendar c = Calendar.getInstance();
    	int Year = c.get(Calendar.YEAR);
    	int Month = c.get(Calendar.MONTH)+1;
    	int Day = c.get(Calendar.DAY_OF_MONTH);
    	int Hour = c.get(Calendar.HOUR_OF_DAY);
    	int Minute = c.get(Calendar.MINUTE);
    	int Second = c.get(Calendar.SECOND);
    	
    	if(dayORtime) {
    		return String.format("%4d%02d%02d_%02d%02d%02d",Year,Month,Day,Hour,Minute,Second);
    	}else {
    		return String.format("%02d%02d%02d",Hour,Minute,Second);
    	}	
	}
	
	public boolean getBoolean_pref(String pref_string)
    {
    	return mUserSharedPreference.getBoolean_pref(pref_string);
    }
    
    public void setBoolean_pref(String pref_string, boolean _value)
    {
    	mUserSharedPreference.setBoolean_pref(pref_string, _value);
    }
    
    public int getInt_pref(String pref_string)
    {
    	return mUserSharedPreference.getInt_pref(pref_string);
    }
    
    public void setInt_pref(String pref_string, int _value)
    {
    	mUserSharedPreference.setInt_pref(pref_string, _value);
    }
}
